package de.sas.za_gui.shell;

import java.util.List;
import java.util.concurrent.CyclicBarrier;

public class Computer implements Runnable
{
	static CyclicBarrier barrier;
	static Cell[][] field;
	static List<Integer> allowedToStayAlive;
	static List<Integer> allowedToGetAlive;
	int x, y;
	int width, height;
	Cell[][] fieldPart;

	public Computer(CyclicBarrier bar, int x, int y, int width, int height)
	{
		barrier = bar;
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;
	}

	@Override
	public void run()
	{
		try
		{
			extractFieldPart();
			barrier.await();
			computeNextStep();
			barrier.await();
		}
		catch (Exception err)
		{
			System.out.println("Exception in run");
		}
	}

	private void computeNextStep()
	{
		for (int i = 1; i < fieldPart.length - 1; i++)
		{
			for (int j = 1; j < fieldPart[0].length - 1; j++)
			{
				int neighboursAlive = countNeighboursAlive(fieldPart, i, j);

				if (fieldPart[i][j].isAlive())
				{
					if (!allowedToStayAlive.contains(neighboursAlive))
					{
						field[x + i - 1][y + j - 1].setAlive(false);
					}
				}
				else
				{
					if (allowedToGetAlive.contains(neighboursAlive))
					{
						field[x + i - 1][y + j - 1].setAlive(true);
					}
				}
			}
		}
	}

	private void extractFieldPart()
	{
		fieldPart = new Cell[width + 2][height + 2];
		for (int i = 0; i < fieldPart.length; i++)
		{
			for (int j = 0; j < fieldPart[0].length; j++)
			{
				int nextX = x + i - 1 < field.length ? x + i - 1 : 0;
				nextX = nextX < 0 ? field.length - 1 : nextX;
				int nextY = y + j - 1 < field[0].length ? y + j - 1 : 0;
				nextY = nextY < 0 ? field[0].length - 1 : nextY;
				fieldPart[i][j] = new Cell(field[nextX][nextY].isAlive());
			}
		}
	}

	private int countNeighboursAlive(Cell[][] field, int x, int y)
	{
		int count = 0;
		for (int i = x - 1; i <= x + 1; i++)
		{
			for (int j = y - 1; j <= y + 1; j++)
			{
				if (i == 1 && j == 1)
				{
					continue;
				}
				if (field[i][j].isAlive())
				{
					count++;
				}
			}
		}
		return count;
	}
}
